﻿// See https://aka.ms/new-console-template for more information
using CSharpBasicGrammar.Unity;
using System.Reflection;
using Zhaoxi.AdvancedCourse.GenericClasses;
using Zhaoxi.AdvancedCourse.Models;

Console.WriteLine("Hello, World!");

#region 泛型约束代码实例
{
    //泛型约束
    //1.值类型约束
    string strVal = "5.5559";
    float fVal = GenericMethodClass.ToType<float>(strVal);

    //2.引用类型约束
    RecordList<ExpendInfo> recordList01 = new RecordList<ExpendInfo>();//没有问题 ExpendInfo是引用类型

    //3.基类约束
    IncomeInfo income1 = new IncomeInfo()
    {
        Id = 101,
        Remark = "银行转账",
        Amount = 800
    };
    GenericMethodClass.GetRecordInfo(income1); //正确的   IncomeInfo 是RecordBase的子类

    //4.接口约束-调用方法
    GenericMethodClass.totalAmount = 10000; // 记录收入1万元
    ExpendInfo expendInfo = new ExpendInfo()
    {
        Id = 104,
        Remark = "生活买菜",
        Amount = 85
    };
    decimal totalAmount = GenericMethodClass.GetTotalAmount(expendInfo);//正确 ExpendInfo类派生于RecordBase且实现了IRecord接口

    //5.无参构造函数约束
    //场景：不知道具体类型是什么时，我想提供一个方法：对于任何引用类型，可以创建该具体的对象
    //一个方法来解决不同类型实例的创建方式
    Student student1 = GenericMethodClass.CreateModel<Student>(); // 可以创建任何引用类型的实例
    student1.Id = 1011;
    student1.Name = "李明";
    Teacher teacher1 = GenericMethodClass.CreateModel<Teacher>();
    IncomeInfo incomeInfo = GenericMethodClass.Create<IncomeInfo>();
    expendInfo = GenericMethodClass.Create<ExpendInfo>();

    #region 泛型计算器实例
    {
        GenericMethodClass genericClass = new GenericMethodClass();
        int result1 = genericClass.Add<int, int, int>(100, 200); // int类型的假发运算
        double result2 = genericClass.Add<double, double, double>(100.68, 20.45); // double类型的加法运算

        Console.WriteLine(result1);
        Console.WriteLine(result2);

        //使用泛型可以有效的节省代码，并且维护非常方便
        Console.ReadLine();
    }
    #endregion
}
#endregion

#region 反射代码实例
{ //动态实例化对象
  //不直接使用类型  类名---类型对象----创建实例----显式转换成对应类型
    string fullName = "Zhaoxi.AdvancedCourse.Models.IncomeInfo";//完整名称
    Type incomeType = Type.GetType(fullName);//获取类型对象
    object oIncome = Activator.CreateInstance(incomeType);  // 实例化对象
    IncomeInfo incomeNew = (IncomeInfo)oIncome;
}

{ // 反射操作属性与字段
  //查看元数据
    ItemInfo item = new ItemInfo()
    {
        Id = 101,
        ItemType = "收入",
        ItemName = "银行转账"
    };
    item.remark = "通过银行转账获取收入";
    Type typeItem = typeof(ItemInfo);//类型对象
                                     //1.属性
    PropertyInfo[] properties = typeItem.GetProperties();//获取所有公开的属性数组

    foreach (PropertyInfo property in properties)
    {  //不通过直接代码访问，读取对象中的属性值：  属性名--属性值
       //property.Name  获取属性名称   property.GetValue(obj) 获取obj对象中property属性的值
        Console.WriteLine(property.Name + "：" + property.GetValue(item).ToString());
    }
    //获取ItemType属性的值
    PropertyInfo itemTypeProp = typeItem.GetProperty("ItemType");//获取ItemType属性
    string itemType = itemTypeProp.GetValue(item).ToString();//获取ItemType属性的值     收入
                                                             //修改属性值
    item.ItemName = "工资发放";//直接代码修改
    typeItem.GetProperty("ItemName").SetValue(item, "朋友还钱");//通过属性对象来修改ItemName的属性值
    foreach (PropertyInfo property in properties)
    {
        Console.WriteLine(property.Name + "：" + property.GetValue(item).ToString());
    }
    //2.字段
    //公有字段
    var fileds = typeItem.GetFields(); // 获取所有公开字段
    FieldInfo fRemark = typeItem.GetField("remark");//获取指定名称的字段
    fRemark.SetValue(item, "通过工资发放");//修改字段的值
    string remark = fRemark.GetValue(item).ToString();//获取字段的值
    Console.WriteLine("字段remark:" + remark);
    FieldInfo fType = typeItem.GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance);//获取私有字段
    string typeStr = fType.GetValue(item).ToString();//获取字段的值
}

{ // 反射操作方法
    ItemInfo item = new ItemInfo()
    {
        Id = 101,
        ItemType = "收入",
        ItemName = "银行转账"
    };
    item.remark = "通过银行转账获取收入";
    Type typeItem = typeof(ItemInfo);//类型对象

    //反射方式调用
    //获取方法
    MethodInfo[] methods = typeItem.GetMethods(); // 获取所有公开方法
    foreach (MethodInfo method in methods)
    {
        Console.WriteLine(method.Name);//方法名 - 循环输出所有方法名
    }
    //获取指定的方法
    MethodInfo getItemInfo = typeItem.GetMethod("GetItemInfo");
    //调用方法  无参方法  没有参数--null
    string reStr = getItemInfo.Invoke(item, null).ToString();

    MethodInfo getCount = typeItem.GetMethod("GetCount"); // 获取指定方法
    //调用静态方法  第一个参数：null 
    int reCount = (int)getCount.Invoke(null, null);  // 调用静态方法- 调用静态方法时不需要实例，所以第一个参数传null

    Console.WriteLine(reStr);
    //获取带一个参数的方法
    MethodInfo setCount = typeItem.GetMethod("SetCount", new Type[] { typeof(int) }); // 获取重载的方法
    int count = 5;
    //调用一个参数的方法
    setCount.Invoke(item, new object[] { count }); // 调用方法以及传值
    Console.WriteLine("数量：" + ItemInfo.count);
    setCount.Invoke(item, new object[] { 6 });
    Console.WriteLine("数量：" + ItemInfo.count);

    ExpendInfo expendInfo = new ExpendInfo();
    Type expendType = typeof(ExpendInfo);
    //获取带一个参数的方法
    MethodInfo addAmount = expendType.GetMethod("AddAmount", new Type[] { typeof(decimal), typeof(decimal) }); // 获取带两个参数的方法
    decimal amount1 = 300m, amount2 = 50m;
    //调用两个参数的方法
    decimal totalAmount = (decimal)addAmount.Invoke(expendInfo, new object[] { amount1, amount2 });  // 调用带两个参数的方法
    Console.WriteLine("总金额：" + totalAmount);

    //补充：泛型方法获取与调用
    MethodInfo createObj = typeof(GenericMethodClass).GetMethod("CreateObj");//获取方法
    MethodInfo createObjNew = createObj.MakeGenericMethod(typeof(IncomeInfo));//转换为泛型方法，传入实际类型对象
    IncomeInfo income = (IncomeInfo)createObjNew.Invoke(null, null);//调用泛型方法，创建一个实例
}

{  // 反射操作构造函数
   //获取类型，创建实例
    Type incomeType = typeof(IncomeInfo);
    //object incomeObj = Activator.CreateInstance(incomeType);
    //获取构造函数
    //1). 无参构造函数
    ConstructorInfo cons0 = incomeType.GetConstructor(new Type[] { });
    //调用无参构造函数创建一个默认实例
    IncomeInfo income0 = (IncomeInfo)cons0.Invoke(null);
    //2) 带一个参数的构造函数
    ConstructorInfo cons1 = incomeType.GetConstructor(new Type[] { typeof(int) });
    //调用带一个参数构造函数创建一个实例
    int id = 102;
    IncomeInfo income1 = (IncomeInfo)cons1.Invoke(new object[] { id });
    //3) 带2个参数的构造函数
    ConstructorInfo cons2 = incomeType.GetConstructor(new Type[] { typeof(int), typeof(decimal) });
    //调用带2个参数构造函数创建一个实例
    int id1 = 103;
    decimal amount1 = 300;
    IncomeInfo income2 = (IncomeInfo)cons2.Invoke(new object[] { id1, amount1 });
    //4) 带3个参数的构造函数
    ConstructorInfo cons3 = incomeType.GetConstructor(new Type[] { typeof(int), typeof(string), typeof(decimal) });
    //调用带3个参数构造函数创建一个实例
    int id2 = 104;
    decimal amount2 = 100;
    IncomeInfo income3 = (IncomeInfo)cons3.Invoke(new object[] { id2, "发奖金", amount2 });
}

{
    //动态加载程序集
    Assembly assModels = null;
    //1) Load  传入程序集文件名，不带.dll后缀名  dll文件放入起始位置  .Net8 识别不到程序 .netframework平台支持
    //Models项目添加引用进来，这种方式就可以
    //assModels = Assembly.Load("Zhaoxi.Models.dll");
    //2) LoadFile 传入程序集文件的完整路径（绝对路径） 绝对路径加载
    assModels = Assembly.LoadFile("D:\\工作\\基础班Vip05\\Zhaoxi.AdvancedCourse\\Zhaoxi.AdvancedCourse\\bin\\Debug\\net8.0\\Zhaoxi.Models.dll");
    //3)LoadFrom(程序集文件名,带.dll后缀名)
    assModels = Assembly.LoadFrom("Zhaoxi.Models.dll"); // 程序集要在程序根目录中

    Type stuType = assModels.GetType("Zhaoxi.Models.Student"); // 获取类型对象
    Student stu = (Student)Activator.CreateInstance(stuType); // 创建实例对象
}

{
    //反射与泛型结合应用
    ModelBase<ItemInfo> baseItem = new ModelBase<ItemInfo>();
    baseItem.Add(new ItemInfo() { Id = 101, ItemType = "收入", ItemName = "银行转账" });
    baseItem.Add(new ItemInfo() { Id = 102, ItemType = "支出", ItemName = "买菜" });
    var itemList = baseItem.GetList();
    foreach (var item in itemList)
    {
        Console.WriteLine(baseItem.GetInfo(item));
    }
    ItemInfo item1 = baseItem.Find(102, "Id");

    ModelBase<IncomeInfo> baseIncome = new ModelBase<IncomeInfo>();
    baseIncome.Add(new IncomeInfo() { Id = 1, Remark = "工资发放", Amount = 3000 });
    baseIncome.Add(new IncomeInfo() { Id = 2, Remark = "银行转账", Amount = 1000 });
    var incomeList = baseIncome.GetList();
    foreach (var income in incomeList)
    {
        Console.WriteLine(baseIncome.GetInfo(income));
    }
}

#endregion